#include <interr.h>

static sys_irq_handle_t irqTable[NUMBER_OF_INT_VECTORS];


void int_init(void)
{
    PLIC_Init();             
    system_irqtable_init();	  
}

void clint_timer_init(void)
{
	csr_clear(mie, MIE_MTIE | MIE_MSIE);
	write32(CLINT + 0x4000, + 24000000);
    write32(CLINT + 0x4004, 0);
    csr_set(mie,  MIE_MTIE); 
}


void system_irqtable_init(void)
{
	unsigned int i = 0;
	
	for(i = 0; i < NUMBER_OF_INT_VECTORS; i++)
	{
		system_register_irqhandler((IRQn_Type)i,default_irqhandler, NULL);
	} 
}


void system_register_irqhandler(IRQn_Type irq, system_irq_handler_t handler, void *userParam) 
{
	irqTable[irq].irqHandler = handler;
  	irqTable[irq].userParam = userParam;
}


void system_irqhandler(void) 
{
   uint32_t IRQID=read32(PLIC_MCLAIM);
   if ((IRQID <0) || (IRQID >= NUMBER_OF_INT_VECTORS))
   {
	 	return;
   }
   irqTable[IRQID].irqHandler(IRQID, irqTable[IRQID].userParam);
   write32(PLIC_MCLAIM, IRQID);
}




void default_irqhandler(unsigned int giccIar, void *userParam) 
{
	while(1) 
  	{
   	}
}

void  PLIC_SetPriority(IRQn_Type IRQn, uint8_t priority)
{
	virtual_addr_t addr;
	addr=PLIC_PRIO(IRQn);
	write32(addr, priority);
}
void PLIC_MIE_DisableIRQ(IRQn_Type IRQn)
{
	uint32_t val;
    val = read32(PLIC_MIE(IRQn >> 5));
    val &= ~(1 << (IRQn & 0x1f));
	write32(PLIC_MIE(IRQn >> 5), val);
}

void PLIC_MIE_EnableIRQ(IRQn_Type IRQn)
{
	uint32_t val;
    val = read32(PLIC_MIE(IRQn >> 5));
    val |= (1 << (IRQn & 0x1f));
	write32(PLIC_MIE(IRQn >> 5), val);

}
void PLIC_SetPendingIRQ(IRQn_Type IRQn)
{
	uint32_t val;
    val = read32(PLIC_IP(IRQn >> 5));
    val |= (1 << (IRQn & 0x1f));
	write32(PLIC_IP(IRQn >> 5), val);
}

void PLIC_Init(void)
{
    uint32_t val;
    int i;
    /*
	 * Disable all interrupts
	 */
    for(i=0;i<NUMBER_OF_INT_VECTORS;i++)
    {
        val = read32(PLIC_MIE(i >> 5));
        val &= ~(1 << (i & 0x1f));
		write32(PLIC_MIE(i >> 5), val);
    }
    /*
	 * Set all source priorities to one
	 */
    for(i = 1; i < NUMBER_OF_INT_VECTORS; i++)
	{
		write32(PLIC_PRIO(i), 1);
	}
    /*
	 * Clear pending bits
	 */
	for(i = 0; i < NUMBER_OF_INT_VECTORS; i++)
	{
		write32(PLIC_MCLAIM, i);
	}
}
void Sys_ResetExecute(void)
{
    WDOG_SOFT_RST = 0x16aa0001;
}

